/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
					     dialog_school_of_magic.cpp

	$Header: /game/dialog_school_of_magic.cpp $

	$NoKeywords: $

 ************************************************************************/
// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_school_of_magic.h"

#include "adaptor_handler.h"
#include "army.h"
#include "basic_dialog.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "creature_icon_window.h"
#include "creature_select_window.h"
#include "dialog_magic_university.h"
#include "external_string.h"
#include "format_string.h"
#include "game_replace_keywords.h"
#include "hero.h"
#include "interface_help.h"
#include "player.h"
#include "random.h"
#include "skill.h"
#include "skill_button.h"
#include "skill_properties.h"
#include "standard_fonts.h"
#include "text_window.h"
#include "school_of_magic.h"

const   int k_skill_cost    = 2000;

extern t_external_string const		k_hotkey_buy;
extern t_button_cache			    g_ok_button;
extern t_button_cache const			k_learn_button;

static t_bitmap_group_cache const	k_school_of_magic_bitmaps( "dialog.school_of_magic" );


/*
** School of Magic dialog constructor.
*/
t_dialog_school_of_magic::t_dialog_school_of_magic ( t_window* parent )
					: t_window( k_completely_transparent, parent )
{
	m_skill_frames = k_skill_frames.get();
}

/*
** Create skill toggle buttons
*/
void t_dialog_school_of_magic::create_skill_toggle_buttons (t_screen_rect skill_rect, t_skill skill, t_window* parent_window, int id)
{
	t_toggle_button*		toggle_button_ptr;
	t_button_handler        button_handler;

    /*
    ** Create toggle button shell - enable radio button.
    */
	toggle_button_ptr = new t_toggle_button( skill_rect.top_left(), parent_window, true );

	create_skill_button( toggle_button_ptr, skill, m_skill_frames );

	button_handler = add_2nd_argument( bound_handler( *this, &t_dialog_school_of_magic::choose_skill ), id);
	//button_handler = bound_handler( *this, &t_dialog_school_of_magic::choose_skill );
	toggle_button_ptr->set_click_handler( button_handler );

	m_skill_button_group.add( toggle_button_ptr );
}

/*
** Initialize the text, icons, buttons, etc.
*/
void t_dialog_school_of_magic::init_dialog( std::vector<t_hero*> const& heroes, t_window* parent, t_single_use_object const& object, 
                t_army* army, t_skill_type skill_1, t_skill_type skill_2)
{
	t_screen_rect           rect;
	t_bitmap_layer const*   layer;
	t_window*               window;
	t_window*               top_window;
	t_window*               background;
	t_screen_point          origin(0,0);
	t_screen_point          point;
    int                     i;
	t_help_block const&		shared_help = get_help_block( "shared" );

    /*
    ** Set init. values.
    */
	m_player_ptr = army->get_owner();
    m_parent_object = &object;
	m_current_cost = 0;
	m_player_funds = m_player_ptr->get_funds()[k_gold];
    m_skill[0] = skill_1;
    m_skill[1] = skill_2;
	m_skill_selected = 0;
	m_bitmaps_ptr = k_school_of_magic_bitmaps.get();
    m_rejected_text = object.get_text ("rejected"); // "help.rejected"

	/*
    ** Create background
    */
	layer = m_bitmaps_ptr->find( "top" );
	top_window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "left" );
	window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "bottom" );
	window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "right" );
	window = new t_bitmap_layer_window( layer, origin, this );

	layer = m_bitmaps_ptr->find( "background" );
	background = new t_bitmap_layer_window( layer, origin, this );
	origin = -layer->get_rect().top_left();

	layer = m_bitmaps_ptr->find( "gold_icon" );
	window = new t_bitmap_layer_window( layer, origin, background );

    /*
    ** Text windows.
    */
	t_text_window* text_window_ptr;
	std::string    text;

	/*
    ** Add the title text.
    */
    text = object.get_text ("name");
	rect = m_bitmaps_ptr->find( "text_title" )->get_rect(); // + origin;
	text_window_ptr = new t_text_window( get_font( 22 ), rect, this, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

	/*
    ** Add the intro text.
    */
	text = object.get_text ("initial");
	rect = m_bitmaps_ptr->find( "text_dialog" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 18 ), rect, background, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    /*
    ** Add the gold cost text - cost of skill upgrade is 2000
    */
	rect = m_bitmaps_ptr->find( "text_gold" )->get_rect() + origin;
	m_cost_window_ptr = new t_text_window( get_font( rect.height() ), rect, background, format_string( "%i", m_current_cost ), 
		                             t_pixel_24(0,0,0) );
	m_cost_window_ptr->set_drop_shadow( true, t_pixel_24(200,200,200) );
	m_cost_window_ptr->set_justification( k_justify_center );

    /*
    ** Add buttons...set and show skill icons.
    */
    t_skill                 skill;
	t_button*               button_ptr;
	t_button_handler        button_handler;

    // Show skill icon 1.
    skill.skill = m_skill[0];
    skill.level = k_mastery_basic;
	rect = m_bitmaps_ptr->find( "icon_1" )->get_rect() + origin;
    create_skill_toggle_buttons ( rect, skill, background, 0 );
    
    // Show name of skill 1.
	text = get_name (skill);
	rect = m_bitmaps_ptr->find( "text_icon_1" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( rect.height()/2 ), rect, background, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    // Show skill icon 2.
    skill.skill = m_skill[1];
    skill.level = k_mastery_basic;
	rect = m_bitmaps_ptr->find( "icon_2" )->get_rect() + origin;
    create_skill_toggle_buttons ( rect, skill, background, 1 );
    
    // Show name of skill 2.
	text = get_name (skill);
	rect = m_bitmaps_ptr->find( "text_icon_2" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( rect.height()/2 ), rect, background, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );
    
    /*
    ** Add hero select windows.
    */
	point = m_bitmaps_ptr->find("hero_portraits")->get_rect().top_left() + origin;

	m_hero_selection_window = new t_creature_select_window( point, false, background );
	for (i = 0; i < heroes.size(); i++)
	{
		m_hero_selection_window->add( heroes[i] );

	    m_hero_selection_window->enable( i, false );
        //m_hero_selection_window->set_help_text( i, rejected_text);
	    m_hero_selection_window->set_help_text( i, heroes[i]->get_name() );
	}
	m_hero_selection_window->set_handler( bound_handler( *this, &t_dialog_school_of_magic::hero_selection_change ));
   
    /*
    ** Add buy button.
    */
	point = m_bitmaps_ptr->find( "purchase_icon" )->get_rect().top_left() + origin;
	m_buy_button = new t_button( k_learn_button.get(), point, background );
	button_handler = bound_handler( *this, &t_dialog_school_of_magic::buy_clicked );
	m_buy_button->set_click_handler( button_handler );
  //m_buy_button->set_help_balloon_text( m_parent_object->get_text ("help.learn") );
  set_help( m_buy_button, shared_help, "learn" );

	/*
    ** Add close button.
    */
	point = m_bitmaps_ptr->find( "close_button" )->get_rect().top_left() + origin;
	button_ptr = new t_button( g_ok_button.get(), point, background );
	button_handler = bound_handler( *this, &t_dialog_school_of_magic::close_clicked );
	button_ptr->set_click_handler( button_handler );
  //button_ptr->set_help_balloon_text( m_parent_object->get_text ("help.close") );
  set_help( button_ptr , shared_help, "ok" );	

    /*
    ** Set the position and display the window.
    */
	t_screen_rect parent_rect = get_parent()->get_client_rect();
    
	rect = m_bitmaps_ptr->get_rect();
	rect += (parent_rect.size() - rect.size()) / 2;
	init( rect );

    /*
    ** Init selection.
    */
    choose_skill (NULL, 0);
    hero_selection_change( NULL, NULL );
}

/*-------------------------------------------------------------------*\
** Clicked on a skill radio button.
\*-------------------------------------------------------------------*/
void t_dialog_school_of_magic::choose_skill( t_button* button, int id )
{
	int                     i;
	t_hero*                 hero_ptr;
  
    /*
    ** If button is NULL, routine is called explicitly, so don't check for it.
    */
    if (button)
    {
    	if (!(button->is_pressed()))
            return;
    }
    /*
    ** Set selected graphic manually because we're calling this routine explicitly.
    */
    else
    {
	    m_skill_button_group.select( id );
    }
   
    /*
    ** Now check which heroes are eligible to buy selected skill.
    */
	m_skill_selected = id;
	m_current_cost = 0;
	std::string    rejected_text = m_parent_object->get_text ("help.rejected");

	for (i = 0; i < m_hero_selection_window->get_count(); i++)
	{
	    m_hero_selection_window->enable( i, false );
        m_hero_selection_window->set_help_text( i, rejected_text );

		hero_ptr = m_hero_selection_window->get_creature(i)->get_hero();

        // Hero visited already (bought skill already).
        if (hero_ptr->has_visited( *m_parent_object ))
        {
            m_hero_selection_window->set_help_text( i, m_parent_object->get_text("help_visited") );
            continue;
        }
            
        // Does hero know this skill already?
        if (hero_ptr->get_skill(m_skill[id]) > k_mastery_none)
        {
            m_hero_selection_window->set_help_text( i, m_parent_object->get_text("help.already_knows") );
            continue;
        }
                    
        // Maxed out skills?  Can never be greater than limit, but just in case...
        if (hero_ptr->get_primary_skill_count() >= k_primary_skill_limit)
        {
            continue;
        }
                    
        // Hero is eligible to buy skill.
	    m_hero_selection_window->enable( i, true );
	    m_hero_selection_window->set_help_text( i, hero_ptr->get_name() );

        /*
        ** Adjust cost as well.
        */
		if (m_hero_selection_window->is_selected(i))
        {
	        m_current_cost += k_skill_cost;
        }
	}
    /*
    ** Show current cost of upgrades.
    */
	m_cost_window_ptr->set_text( format_string( "%i", m_current_cost ) );
	m_hero_selection_window->select_all();

}

/*
** Clicked on the buy button, so buy the skills.
*/
void t_dialog_school_of_magic::buy_clicked( t_button* button )
{
	int i;
	bool		any_heroes_learned = false;
    std::vector<t_hero*> learned_heroes;
    t_skill     skill = t_skill(m_skill[m_skill_selected], k_mastery_basic);

	for (i = 0; i < m_hero_selection_window->get_count(); i++)
    {
		if ((m_hero_selection_window->is_selected(i)) && (m_hero_selection_window->is_enabled (i)))
        {
	        t_hero*     hero_ptr = m_hero_selection_window->get_creature(i)->get_hero();
           
            // Hero learns bought skill.
	        hero_ptr->learn_skill( skill, true );
	        hero_ptr->set_visited( *m_parent_object );
		    learned_heroes.push_back( hero_ptr );
	        any_heroes_learned = true;
        }
    }
	m_player_ptr->spend( k_gold, m_current_cost );
	m_player_funds = m_player_ptr->get_funds()[k_gold];

    // Display result.
    if (any_heroes_learned)
    {
	    std::string result_text = replace_keywords( m_parent_object->get_text("paid"), 
						"%skill_name", ::get_name( skill ) );

        display_skill( skill, this, learned_heroes, result_text );
    }
    
    /*
    ** Reset hero windows.
    */
    choose_skill (NULL, m_skill_selected);

}

/*
** Hero selection handler.
*/
void t_dialog_school_of_magic::hero_selection_change( t_creature_select_window*, t_creature_stack* )
{
	int i;

	m_current_cost = 0;

	for (i = 0; i < m_hero_selection_window->get_count(); i++)
    {
		if ((m_hero_selection_window->is_enabled(i)) && (m_hero_selection_window->is_selected(i)))
        {
	        t_hero*     hero_ptr;
            
		    hero_ptr = m_hero_selection_window->get_creature(i)->get_hero();
	        m_current_cost += k_skill_cost;
        }
    }

    /*
    ** Show current cost of upgrades.
    */
	m_cost_window_ptr->set_text( format_string( "%i", m_current_cost ) );

    /*
    ** Disable buy button if player doesn't have sufficient funds.
    */
	if ((m_current_cost > m_player_funds) || (m_current_cost == 0)) 
    {
	    m_buy_button->enable (false);
	    if (m_current_cost > m_player_funds)
	        m_buy_button->set_help_balloon_text( m_parent_object->get_text ("help.denied") );
        else if (m_current_cost == 0)
	        m_buy_button->set_help_balloon_text( "" );
    }
    else
    {
	    m_buy_button->enable (true);
        m_buy_button->set_help_balloon_text( m_parent_object->get_text ("help.learn") );
    }

}

/*-------------------------------------------------------------------*\
** Clicked on the close button.
\*-------------------------------------------------------------------*/
void t_dialog_school_of_magic::close_clicked( t_button* button )
{
	m_return_value = false;
	close();
}

